<route lang="json5">
{
  style: {
    navigationStyle: 'custom',
    navigationBarTitleText: '讨论组',
    enablePullDownRefresh: false,
    'app-plus': {
      bounce: 'none',
    },
  },
}
</route>
<template>
  <view id="chat-box">
    <NavBar>
      <template v-slot:left>
        <text class="iconfont icon-fanhui back"></text>
      </template>
      <template v-slot:title>
        {{ chatInfo.chatName }}
      </template>
      <template v-slot:right>
        <text class="iconfont icon-gengduo" @click="setHandle"></text>
      </template>
    </NavBar>
    <scroll-view
      scroll-y
      id="msg"
      :show-scrollbar="false"
      :scroll-top="msgScrollTop"
      :lower-threshold="200"
      @click="closeHandle"
      @touchstart="closeHandle"
      @scrolltolower="reachTop"
    >
      <view class="content">
        <view style="flex: 1"></view>
        <template v-for="(item, index) in msgList">
          <view v-if="!item.role" :key="item.id" class="item left">
            <view class="f">
              {{ item.senderName?.slice(-1) }}
              <!-- <image  mode="aspectFill" src="../../static/blue.png"></image> -->
            </view>
            <!-- 文字、文件、音频 -->
            <view class="r">
              <view class="name">{{ item.senderName }}</view>
              <view class="c" v-if="[0, 2, 3].includes(item.type)" @click="msgClickHandle(item)">
                <block v-if="item.type === 0">
                  <text>{{ item.content }}</text>
                </block>
                <block v-else-if="item.type === 2">
                  <view class="file-card">
                    <view class="info">
                      <view class="title">{{ item.content }}</view>
                      <view class="size">{{ item.fileSize }}</view>
                    </view>
                    <view class="file-icon" :class="[item.fileType]"></view>
                  </view>
                </block>
                <block v-else>
                  <micro style="margin-right: 15rpx" :play="item.id == inPlay"></micro>
                  <text>{{ item.fileDuration }}″</text>
                </block>
              </view>
              <!-- 图片 -->
              <image
                v-else
                class="b"
                mode="widthFix"
                :class="[item.content]"
                :src="item.fileUrl"
                @click="msgClickHandle(item)"
              ></image>
            </view>
          </view>
          <view v-else :key="item.id" class="item right">
            <!-- 文字、文件、音频 -->
            <view class="r">
              <view
                class="c"
                v-if="[0, 2, 3].includes(item.type)"
                :class="[item.type === 2 ? 'no-bg' : '']"
                @longpress="onLongPress(item)"
                @click="msgClickHandle(item)"
              >
                <block v-if="item.type === 0">
                  <text>{{ item.content }}</text>
                </block>
                <block v-else-if="item.type === 2">
                  <!-- 视频 -->
                  <video
                    v-if="['mp4', 'flv'].includes(item.fileType)"
                    :src="item.fileUrl"
                    controls
                  ></video>
                  <!-- <text v-if="['mp4','flv'].includes(item.fileType)"</text> -->
                  <view v-else class="file-card">
                    <view class="info">
                      <view class="title">{{ item.content }}</view>
                      <view class="size">{{ item.fileSize }}</view>
                    </view>
                    <view class="file-icon" :class="[item.fileType]"></view>
                  </view>
                </block>
                <block v-else>
                  <text>{{ item.fileDuration }}″</text>
                  <micro
                    :play="item.id == inPlay"
                    style="transform: rotate(180deg); margin-left: 15rpx"
                  ></micro>
                </block>
              </view>
              <!-- 图片 -->
              <image
                v-else
                class="b"
                :class="[item.content]"
                mode="widthFix"
                :src="item.fileUrl"
                @longpress="onLongPress(item)"
                @click="msgClickHandle(item)"
              ></image>
            </view>
            <view class="f">
              <!-- <image mode="aspectFill" src="../../static/blue.png"></image> -->
              <!-- {{item.senderName.slice(-1)}} -->
              我
            </view>
            <view v-if="item.role && item.id === revokeId" class="revoke">
              <text @click.stop="revokeHandle(item, index)">撤回</text>
            </view>
          </view>
          <view
            style="
              text-align: center;
              transform: rotate(180deg);
              color: #333;
              font-size: 26rpx;
              margin: 15rpx;
              position: relative;
              z-index: -1;
            "
          >
            {{ item.formatTime }}
          </view>
        </template>
      </view>
    </scroll-view>
    <view id="place-block" :style="{ height: translateY + increaseHeight + 51 + 'px' }"></view>
    <view id="send" :style="{ bottom: translateY + 'px' }">
      <view
        class="iconfont audio"
        :class="[mode === 'text' ? 'icon-yuyin' : 'icon-jianpan']"
        @click="changeMode"
      ></view>
      <scroll-view
        v-if="mode !== 'audio'"
        scroll-y
        :scroll-top="scrollTop"
        :scroll-with-animation="true"
        class="text"
      >
        <textarea
          class="textarea"
          v-model="msg"
          :confirm-hold="true"
          :auto-height="true"
          :adjust-position="false"
          :focus="autoFocus"
          @input="textChange"
          @linechange="textLineChange"
        ></textarea>
      </scroll-view>
      <record v-if="mode === 'audio'" @send="sendHandle"></record>
      <view class="iconfont face icon-smile" @click="showOthers('emoji')"></view>
      <view
        class="iconfont other icon-xinzeng"
        v-if="!sendVisible"
        @click="showOthers('file')"
      ></view>
      <button
        class="send-handle"
        :class="[sendVisible ? 'show' : '']"
        @touchend.prevent="sendHandle"
      >
        发送
      </button>
    </view>
    <view
      id="others"
      :class="[otherVisible ? 'show' : '']"
      :style="{ height: translateY || 284 + 'px' }"
      style="bottom: 0"
    >
      <view class="tools" v-if="mode === 'file'">
        <view class="t iconfont gallery icon-xiangce" @click="chooseMedia">
          <text>图片</text>
        </view>
        <!-- 				<view class="t iconfont camera icon-xiangji" @click="chooseVideo">
					<text>视频</text>
				</view> -->
        <view class="t iconfont doc icon-file" @click="openFile">
          <text>文件</text>
        </view>
        <view class="t iconfont icon-danju-tianchong" @click="toPage">
          <text>查看单据</text>
        </view>
        <view class="t iconfont icon-danju-tianchong" style="opacity: 0">
          <text>占位</text>
        </view>
      </view>
      <view class="emoji" v-if="mode === 'emoji'">
        <image
          v-for="(emoji, index) in emojiJson"
          :key="index"
          :src="emoji.expressionUrl"
          class="emoji-img"
          mode="aspectFill"
          @click="sendEmojiHandle(emoji)"
        ></image>
      </view>
    </view>
  </view>
</template>

<script>
import { sendMessage, getMessage, getGroupChatById, deleteChatMsg, getEmoji } from '@/service/chat';
import cache from '@/utils/cache';
import dayjs from 'dayjs';
import { requestAndroidPermission } from './permission.js';
import record from './record.vue';
import micro from './components/micro.vue';
import NavBar from './components/navBar.vue';

import 'dayjs/locale/zh-cn';

const recorderManager = uni.getRecorderManager();
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = false;
dayjs.locale('zh-cn');

/*
	  0文字 1图片 2文件 3音频
	*/
export default {
  components: {
    record,
    micro,
    NavBar,
  },
  data() {
    return {
      translateY: 0, // 工具栏上移距离
      KeyboardHeight: 0, // 键盘高度
      lineHeight: 0, // 默认行高
      increaseHeight: 0, // 增加的行高
      msgScrollTop: 0,
      scrollTop: 0,
      params: {
        size: 30,
        current: 1,
      },
      mode: 'text', // 输入方式 语音/文字
      otherVisible: false, // 工具栏显示
      autoFocus: false, // 自动获取焦点
      sendVisible: false, // 发送按钮显隐
      inSendIng: false,
      msg: '', // 待发送内容
      last: '',
      fileList: [],
      scrollIntoIndex: '',
      topIndex: 0,
      msgList: [],
      shiftMsg: [],
      rest: 0,
      inPlay: '',
      canShift: true,
      times: 0,
      scrolTop: 0,
      old: {
        scrolTop: 0,
      },
      oldheight: 0, // 标签位置
      newheight: 0, // 新窗口高度
      chatInfo: {},
      user: '',
      loadMore: true,
      revokeId: '',
      emojiJson: [],
    };
  },
  methods: {
    setHandle() {
      uni.navigateTo({
        url: `/pages/chat/groupSetting?chatId=${this.chatInfo.id}`,
      });
    },
    checkRecordAuth() {
      return new Promise((resolve) => {
        requestAndroidPermission('android.permission.RECORD_AUDIO').then((res) => {
          if (res !== 1) {
            resolve(false);
          } else {
            resolve(true);
          }
        });
      });
    },
    async changeMode() {
      if (this.mode === 'text') {
        const hasAuth = await this.checkRecordAuth();
        if (!hasAuth) {
          uni.showModal({
            title: '提示',
            content: '没有录音权限，请前往授权麦克风',
            success(res) {
              if (res.confirm) {
                uni.openAppAuthorizeSetting();
              }
            },
          });
          return;
        }
        this.otherVisible = false;
        this.translateY = 0;
        this.sendVisible = false;
        this.mode = 'audio';
      } else {
        this.mode = 'text';
        this.autoFocus = true;
        if (this.msg) {
          this.sendVisible = true;
        }
      }
    },
    showOthers(mode) {
      this.mode = mode;
      this.otherVisible = true;
      // if (this.otherVisible) {
      // 	// this.otherVisible = false;
      // 	this.autoFocus = true;
      // } else {
      // 	// this.mode = 'text'
      // 	// this.mode = mode;
      // 	this.otherVisible = true;
      // 	this.autoFocus = false;
      this.translateY = this.KeyboardHeight || 284;
      // }
    },
    closeHandle() {
      this.autoFocus = false;
      this.otherVisible = false;
      this.translateY = 0;
      uni.hideKeyboard();
      setTimeout(() => {
        this.revokeId = '';
      }, 300);
    },
    textChange(e) {
      if (e.detail.value.length) {
        this.sendVisible = true;
      } else {
        this.sendVisible = false;
      }
    },
    textLineChange(e) {
      const { height, lineCount } = e.detail || e.target;
      if (!this.lineHeight) this.lineHeight = height;
      const r = height - this.lineHeight;
      // 计算
      this.increaseHeight = r > 200 ? 200 : r;
      // setTimeout(() => {
      // 	this.msgScrollTop = Date.now()
      // 	this.scrollTop = this.msgScrollTop
      // })
    },
    sendMessages(data) {
      return new Promise((resolve) => {
        const msg = {
          chatId: this.chatInfo.id,
          id: Date.now(),
          senderCode: this.username,
          ...data,
        };
        sendMessage(msg).then((res) => {
          if (res.code === 0) {
            const nMsg = { ...msg };
            nMsg.formatTime = this.formatTime(dayjs().format('YYYY-MM-DD HH:mm:ss'));
            if (nMsg.type === 2 && nMsg.fileUrl) {
              const arr = msg.fileUrl.split('.');
              nMsg.fileType = arr[arr.length - 1];

              if (nMsg.fileSize) {
                if (nMsg.fileSize > 1024 * 1024) {
                  nMsg.fileSize = `${Number((nMsg.fileSize / 1024 / 1024).toFixed(2))}M`;
                } else {
                  nMsg.fileSize = `${Number((nMsg.fileSize / 1024).toFixed(2))}K`;
                }
              }
            }
            console.log('00000', nMsg);
            this.msgList.unshift({
              ...nMsg,
              role: 1,
            });
            resolve(true);
          } else {
            uni.showToast({
              title: '发送失败，请重试',
              icon: 'none',
            });
            resolve(false);
          }
        });
      });
    },
    sendHandle(ref) {
      if (this.inSendIng) return;
      let msg = {};
      if (ref && ref.type === 3) {
        msg = {
          type: 3,
          fileDuration: ref.fileDuration,
          fileUrl: ref.fileUrl,
          content: ref.content,
        };
      } else {
        if (!this.msg) {
          uni.showToast({
            title: '请输入内容',
            icon: 'none',
          });
          return;
        }
        msg = {
          type: 0,
          content: this.msg,
        };
      }
      this.inSendIng = true;
      this.sendMessages(msg).then((res) => {
        if (res) {
          this.msg = '';
          this.sendVisible = false;
        }
        this.inSendIng = false;
      });
    },
    sendEmojiHandle(emoji) {
      const msg = {
        type: 1,
        fileUrl: emoji.expressionUrl,
        content: 'emoji',
      };
      this.sendMessages(msg);
    },
    reachTop() {
      this.getMessageHandle();
    },
    msgClickHandle(item) {
      switch (item.type) {
        case 0:
          console.log('copy');
          break;
        case 1:
          this.previewImage(item);
          break;
        case 2:
          this.openDocument(item);
          break;
        case 3:
          this.playVoice(item);
          break;
        default:
          break;
      }
    },
    revokeHandle(item, index) {
      deleteChatMsg([item.id]).then((res) => {
        this.msgList.splice(index, 1);
      });
    },
    previewImage(item) {
      if (item.content === 'emoji') return;
      const images = this.msgList
        .filter((msg) => msg.type === 1 && msg.content !== 'emoji')
        .reverse();
      const urls = images.map((img) => img.fileUrl);
      let current = 0;
      images.forEach((img, ind) => {
        if (img.id === item.id) {
          current = ind;
        }
      });

      uni.previewImage({
        current,
        urls,
      });
    },
    openDocument(item) {
      if (item.tempFilePath) {
        uni.openDocument({
          filePath: item.tempFilePath,
          showMenu: true,
        });
        return;
      }
      uni.showLoading({
        title: '正在下载',
      });
      uni.downloadFile({
        url: item.fileUrl,
        success(res) {
          uni.hideLoading();
          const filePath = res.tempFilePath;
          item.tempFilePath = res.tempFilePath;
          uni.openDocument({
            filePath,
            showMenu: true,
          });
        },
      });
    },
    playVoice(item) {
      if (this.inPlay === item.id) {
        innerAudioContext.stop();
        this.inPlay = '';
        return;
      }
      innerAudioContext.stop();
      innerAudioContext.src = item.fileUrl;
      if (plus.device.getVolume() < 0.1) {
        uni.showToast({
          title: '播放音量可能过低',
          icon: 'none',
        });
      }
      innerAudioContext.play();

      this.inPlay = item.id;

      innerAudioContext.onEnded(() => {
        // 自动切换事件
        this.inPlay = '';
      });
    },
    async sendMessageQueue(msgs) {
      for (let i = 0; i < msgs.length; i++) {
        const { url, fileSize, fileName } = {
          ...msgs[i],
        };
        await this.sendMessages({
          fileUrl: url,
          fileSize,
          content: fileName,
          type: 1,
        });
      }
    },
    chooseMedia(sourceType = ['camera', 'album']) {
      uni.chooseImage({
        count: 9,
        sizeType: ['original', 'compressed'],
        sourceType,
        mediaType: 'mix',
        success: (files) => {
          const tempFiles = files.tempFiles.map((file, index) => {
            return {
              id: new Date().getTime(),
              progress: 0,
              type: 1,
              path: file.path,
            };
          });
          const promises = [];
          uni.showLoading({
            title: '发送中',
            mask: true,
          });
          for (let i = 0; i < tempFiles.length; i++) {
            promises.push(this.uploadFile(tempFiles[i].path));
          }

          Promise.all(promises)
            .then((res) => {
              this.sendMessageQueue(res);
            })
            .finally((err) => {
              uni.hideLoading();
            });
        },
      });
    },
    chooseVideo(sourceType = ['album', 'camera']) {
      uni.chooseVideo({
        sourceType,
        success: (file) => {
          uni.showLoading({
            title: '发送中',
            mask: true,
          });
          this.uploadFile(file.tempFilePath).then(async (res) => {
            const msg = {
              type: 2,
              fileUrl: res.url,
              fileSize: res.fileSize,
              fileDuration: file.duration,
              content: res.fileName,
            };
            const r = await this.sendMessages(msg);
            uni.hideLoading();
          });
        },
      });
    },
    uploadFile(path) {
      return new Promise((resolve) => {
        uni.uploadFile({
          // url: `https://testappthwater.thwater.com:30080/api/oss/sysOss/upload`,
          url: `${import.meta.env.VITE_SERVER_BASEURL}/oss/sysOss/upload`,
          filePath: path,
          name: 'file',
          header: {
            Authorization: cache.get('token'),
          },
          success: (res) => {
            const resp = JSON.parse(res.data);
            resolve(resp.data);
          },
          fail: (err) => {
            console.log(err, 'err');
            resolve(false);
          },
        });
      });
    },
    toPage() {
      if (!this.chatInfo.appRelationUrl) {
        uni.showToast({
          title: '未配置单据地址',
          icon: 'none',
        });
      }
      uni.navigateTo({
        url: this.chatInfo.appRelationUrl,
      });
    },
    openFile() {
      // #ifdef APP-PLUS
      if (plus.os.name.toLowerCase() != 'android') {
        uni.showModal({
          title: '提示',
          content: '仅支持Android平台',
          success(res) {},
        });
        return false;
      }
      const that = this;
      // java 代码来自 http://www.cnblogs.com/panhouye/archive/2017/04/23/6751710.html
      const main = plus.android.runtimeMainActivity();
      const Intent = plus.android.importClass('android.content.Intent');

      //
      const fileIntent = new Intent(Intent.ACTION_GET_CONTENT);
      // fileIntent.setType(“image/*”);//选择图片
      // fileIntent.setType(“audio/*”); //选择音频
      // fileIntent.setType(“video/*”); //选择视频 （mp4 3gp 是android支持的视频格式）
      // fileIntent.setType(“video/*;image/*”);//同时选择视频和图片
      fileIntent.setType('*/*'); // 无类型限制
      fileIntent.addCategory(Intent.CATEGORY_OPENABLE);
      main.startActivityForResult(fileIntent, 1);
      // 获取回调
      main.onActivityResult = async function (requestCode, resultCode, data) {
        const Activity = plus.android.importClass('android.app.Activity');
        const ContentUris = plus.android.importClass('android.content.ContentUris');
        const Cursor = plus.android.importClass('android.database.Cursor');
        const Uri = plus.android.importClass('android.net.Uri');
        const Build = plus.android.importClass('android.os.Build');
        const Environment = plus.android.importClass('android.os.Environment');
        const DocumentsContract = plus.android.importClass('android.provider.DocumentsContract');
        const MediaStore = plus.android.importClass('android.provider.MediaStore');
        // 给系统导入 contentResolver
        const contentResolver = main.getContentResolver();
        plus.android.importClass(contentResolver);
        // 返回路径
        let path = '';
        if (resultCode == Activity.RESULT_OK) {
          const uri = data.getData();
          if (uri.getScheme().toLowerCase() == 'file') {
            // 使用第三方应用打开
            path = uri.getPath();
            return;
          }
          if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
            // 4.4以后
            path = getPath(this, uri);
          } else {
            // 4.4以下下系统调用方法
            path = getRealPathFromURI(uri);
          }
          // 回调
          const res = await that.uploadFile(path);
          await that.sendMessages({
            content: res.fileName,
            fileSize: res.fileSize,
            fileUrl: res.url,
            type: 2,
          });
          // that.$emit('result', path)
        }
        // 4.4 以上 从Uri 获取文件绝对路径
        function getPath(context, uri) {
          const isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
          const scheme = uri.getScheme().toLowerCase();
          if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
              const docId = DocumentsContract.getDocumentId(uri);
              const split = docId.split(':');
              const type = split[0];
              // 如果是手机内部存储
              if (type.toLowerCase() == 'primary') {
                return `${Environment.getExternalStorageDirectory()}/${split[1]}`;
              }
              return `/storage/${type}/${split[1]}`;
            }
            // DownloadsProvider
            if (isDownloadsDocument(uri)) {
              const id = DocumentsContract.getDocumentId(uri);
              const split = id.split(':');
              return split[1];
              // console.log(id)
              // let contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), id);
              // return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            if (isMediaDocument(uri)) {
              const docId = DocumentsContract.getDocumentId(uri);
              const split = docId.split(':');
              const type = split[0];
              let contentUri = null;
              if (type.toLowerCase() == 'image') {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
              } else if (type.toLowerCase() == 'video') {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
              } else if (type.toLowerCase() == 'audio') {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
              }
              const selection = '_id=?';
              const selectionArgs = [split[1]];
              return getDataColumn(context, contentUri, selection, selectionArgs);
            }
          }
          // MediaStore (and general)
          else if (scheme == 'content') {
            return getDataColumn(context, uri, null, null);
          }
          // File
          else if (scheme == 'file') {
            return uri.getPath();
          }
        }
        // 4.4 以下 获取 绝对路径
        function getRealPathFromURI(uri) {
          let res = null;
          const proj = [MediaStore.Images.Media.DATA];
          const cursor = contentResolver.query(uri, proj, null, null, null);
          if (cursor != null && cursor.moveToFirst()) {
            const column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            res = cursor.getString(column_index);
            cursor.close();
          }
          return res;
        }
        // 通过uri 查找出绝对路径
        function getDataColumn(context, uri, selection, selectionArgs) {
          let cursor = null;
          const column = '_data';
          const projection = [column];
          // let contentResolver = context.getContentResolver()
          // plus.android.importClass(contentResolver);
          cursor = contentResolver.query(uri, projection, selection, selectionArgs, null);
          if (cursor != null && cursor.moveToFirst()) {
            const column_index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(column_index);
          }
        }

        function isExternalStorageDocument(uri) {
          return uri.getAuthority() == 'com.android.externalstorage.documents';
        }

        function isDownloadsDocument(uri) {
          return uri.getAuthority() == 'com.android.providers.downloads.documents';
        }

        function isMediaDocument(uri) {
          return uri.getAuthority() == 'com.android.providers.media.documents';
        }
      };
      // #endif
      // #ifndef APP-PLUS
      uni.showModal({
        title: '提示',
        content: '仅支持Android平台',
        success(res) {},
      });
      // #endif
    },
    formatTime(val) {
      const today = dayjs().format('YYYY-MM-DD');
      const tYear = dayjs().format('YYYY');
      const [t1, t2] = val.split(' ');
      const [y, m, d] = t1.split('-');
      if (t1 === today) {
        return dayjs(val).format('HH:mm');
      }
      if (dayjs(t1).add(1, 'day').format('YYYY-MM-DD') === today) {
        return `昨天` + ` ${t2}`;
      }
      return (
        `${(tYear === y ? '' : `${y}年`) + dayjs(t1).format('M')}月${dayjs(t1).format('D')}日` +
        ` ${t2}`
      );
    },
    getMessageHandle() {
      if (!this.loadMore) return;

      // 获取消息
      getMessage({
        ...this.params,
        chatId: this.chatInfo.id,
      }).then((res) => {
        if (res.code === 0) {
          if (res.data.records && !res.data.records.length) return;
          const list = res.data.records.reverse().map((msg) => {
            if (msg.type === 2 && msg.fileUrl) {
              const arr = msg.fileUrl.split('.');
              msg.fileType = arr[arr.length - 1];

              if (msg.fileSize) {
                if (msg.fileSize > 1024 * 1024) {
                  msg.fileSize = `${Number((msg.fileSize / 1024 / 1024).toFixed(2))}M`;
                } else {
                  msg.fileSize = `${Number((msg.fileSize / 1024).toFixed(2))}K`;
                }
              }
            }

            msg.formatTime = this.formatTime(msg.createTime);
            if (msg.senderCode === this.username) {
              msg.role = 1;
            } else {
              msg.role = 0;
            }
            return msg;
          });
          this.msgList = [...this.msgList, ...list];
          // 如果请求的数据大于等于size
          if (list.length === this.params.size) {
            this.params.current += 1;
            this.loadMore = true;
          } else {
            this.loadMore = false;
          }
        }
      });
    },
    onLongPress(item) {
      if ((new Date().getTime() - dayjs(item.createTime).valueOf()) / 120000 < 2) {
        this.revokeId = item.id;
      }
    },
  },
  onShow() {
    uni.$off('sseMsg');
    uni.$on('sseMsg', (msg) => {
      if (msg.senderCode === this.username) return;
      // 如果消息不属于当前讨论组
      if (msg.chatId !== this.chatInfo.id) {
        uni.$emit('receive', msg);
        return;
      }
      const nMsg = { ...msg };
      nMsg.formatTime = this.formatTime(msg.date);
      if (nMsg.type === 2 && nMsg.fileUrl) {
        const arr = msg.fileUrl.split('.');
        nMsg.fileType = arr[arr.length - 1];

        if (nMsg.fileSize) {
          if (nMsg.fileSize > 1024 * 1024) {
            nMsg.fileSize = `${Number((nMsg.fileSize / 1024 / 1024).toFixed(2))}M`;
          } else {
            nMsg.fileSize = `${Number((nMsg.fileSize / 1024).toFixed(2))}K`;
          }
        }
      }
      this.msgList.unshift({
        ...nMsg,
        role: msg.senderCode === this.username ? 1 : 0,
      });
      this.msg = '';
    });

    uni.$off('revokeMsg');
    uni.$on('revokeMsg', (msg) => {
      // 如果消息不属于当前讨论组
      if (msg.chatId !== this.chatInfo.id) {
        uni.$emit('revoke', msg);
        return;
      }
      const ind = this.msgList.findIndex((item) => item.id === msg.id);
      this.msgList.splice(ind, 1);
    });

    uni.$off('resetName');
    uni.$on('resetName', (ref) => {
      this.chatInfo.chatName = ref;
    });
  },
  async onLoad(options) {
    const user = JSON.parse(uni.getStorageSync('app_userCode'));
    this.username = user.value;

    // 获取聊天室信息
    await getGroupChatById(options.chatId).then((res) => {
      if (res.code === 0) {
        this.chatInfo = res.data;
      }
    });

    // 获取表情包
    getEmoji().then((res) => {
      if (res.code === 0) {
        this.emojiJson = res.data;
      }
    });

    this.getMessageHandle();

    uni.onKeyboardHeightChange(async (e) => {
      // 键盘弹出
      if (e.height) {
        this.otherVisible = false;
        this.KeyboardHeight = e.height;
        // this.msgScrollTop = Date.now();
        // 输入框上移动
        this.translateY = e.height;
      } else if (!this.otherVisible) {
        this.translateY = 0;
      }
    });

    this.$nextTick(() => {
      setTimeout(() => {
        const query = uni.createSelectorQuery();
        query.select('#chat-box').boundingClientRect();
        query.selectAll('.item').boundingClientRect();
        query.exec(([v1, v2]) => {
          if (v2.length) {
            this.rest =
              v1.height -
              v2
                .map((item) => item.height)
                .reduce((total, cur) => {
                  return total + cur;
                });
          } else {
            this.rest = v1.height;
          }
        });

        // this.msgScrollTop = Date.now()
      }, 200);
    });
  },
  onUnload() {
    uni.$off('sseMsg');
    uni.$off('revokeMsg');
  },
};
</script>
<style lang="scss">
$baseColor: #e6e6e6;
$border: 1rpx solid $baseColor;

@mixin radius-button {
  width: 78rpx;
  min-width: 78rpx;
  height: 78rpx;
}

#chat-box {
  height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  background: $baseColor;

  // &::-webkit-scrollbar{
  // 	display: none
  // }
  #msg {
    width: 100%;
    overflow: scroll;
    transition: all 1s;
    transform: rotate(180deg);
    transition: all 0.3s;
    flex: 1;

    .item {
      display: flex;
      padding: 0 20rpx;
      margin-top: 30rpx;
      transform: rotate(180deg);

      &.right {
        justify-content: flex-end;
        position: relative;

        .c {
          background: #95ec69;

          &.no-bg {
            background: #fff;
          }

          &::before {
            right: -13rpx;
          }
        }

        .b {
          min-width: 200rpx;

          &.emoji {
            min-width: 60rpx;
            width: 100rpx;
            height: 100rpx;
          }
        }

        .f {
          margin-left: 15rpx;
        }
      }

      &.left {
        justify-content: flex-start;

        .c {
          background: #fff;

          &::before {
            left: -1rpx;
          }
        }

        .f {
          margin-right: 15rpx;
        }

        .b {
          min-width: 200rpx;

          &.emoji {
            min-width: 60rpx;
            width: 100rpx;
            height: 100rpx;
          }
        }

        .name {
          margin-bottom: 4rpx;
          line-height: 100%;
          color: #333;
          font-size: 24rpx;
        }
      }

      .f {
        width: 70rpx;
        height: 70rpx;
        border-radius: 8rpx;
        background: #fff;
        line-height: 70rpx;
        text-align: center;
        font-size: 40rpx;
        font-weight: bold;
        color: #bfbfbf;

        image {
          width: 100%;
          height: 100%;
        }
      }

      .c {
        max-width: 450rpx;
        padding: 15rpx 20rpx;
        font-size: 30rpx;
        border-radius: 8rpx;
        text-align: justify;
        position: relative;
        display: flex;
        align-items: center;

        .file-card {
          display: flex;
          min-width: 450rpx;

          .info {
            flex: 1;

            .title {
              word-break: break-all;
              display: -webkit-box;
              -webkit-box-orient: vertical;
              -webkit-line-clamp: 2;
              overflow: hidden;
              text-overflow: ellipsis;
            }

            .size {
              color: #bfbfbf;
              font-size: 28rpx;
              margin-top: 10rpx;
            }
          }

          .file-icon {
            width: 70rpx;
            height: 70rpx;
            margin: 10rpx 0 0 15rpx;

            &.doc,
            &.docx {
              background: url(@/static/doc/word.png);
              background-size: contain;
            }

            &.pdf,
            &.PDF {
              background: url(@/static/doc/pdf.png);
              background-size: contain;
            }

            &.xlsx {
              background: url(@/static/doc/xlsx.png);
              background-size: contain;
            }

            &.txt {
              background: url(@/static/doc/txt.png);
              background-size: contain;
            }

            &.other {
              background: url(@/static/doc/other.png);
              background-size: contain;
            }
          }
        }

        &::before {
          content: '';
          width: 20rpx;
          height: 20rpx;
          border-radius: 3rpx;
          position: absolute;
          transform: rotate(-45deg) translateX(-50%);
          top: 16rpx;
          background: inherit;
        }
      }

      .b {
        border-radius: 8rpx;
        // max-width: 200rpx;
      }
    }

    .revoke {
      position: absolute;
      top: -40rpx;
      text-align: right;
      margin-right: 90rpx;
      font-size: 26rpx;
      margin-bottom: 15rpx;
      z-index: 99999;
    }
  }

  #send {
    position: fixed;
    bottom: 0;
    width: 100%;
    display: flex;
    width: calc(100% - 50rpx);
    padding: 11rpx 25rpx;
    align-items: flex-end;
    background: #f4f4f4;
    border-bottom: 1rpx solid $baseColor;
    border-top: 1rpx solid $baseColor;
    transition: bottom 0.15s;

    .text {
      max-height: 218px;
      overflow-y: scroll;
      flex: 1;
      padding: 18rpx;
      background: #fff;
      margin-right: 10rpx;
      margin-left: 10rpx;
      border-radius: 10rpx;

      .textarea {
        width: 100%;
        margin: 0;
        padding: 0;
        outline: none;
        font-size: 30rpx;
        caret-color: #95ec69;
      }
    }

    .iconfont {
      text-align: center;
      line-height: 78rpx;
      font-size: 66rpx;
    }

    .audio {
      @include radius-button;
      margin-bottom: -3rpx;
    }

    .face {
      @include radius-button;
      margin-right: 10rpx;
      margin-bottom: -3rpx;
    }

    .other {
      @include radius-button;
      margin-bottom: -3rpx;
    }

    .send-handle {
      width: 0;
      padding: 0;
      mergin: 0;
      height: 62rpx;
      line-height: 62rpx;
      font-size: 28rpx;
      margin-bottom: 7rpx;
      background-color: #07c160;
      color: #fff;
      overflow: hidden;
      transition: all 0.2s;

      &::after {
        border: none;
      }

      &.show {
        width: 120rpx;
      }
    }
  }

  #others {
    position: fixed;
    bottom: 0;
    width: 100%;
    transform: translateY(100%);
    transition: all 0.15s;
    background: #f4f4f4;

    &.show {
      transform: translateY(0);
    }

    .tools {
      display: flex;
      padding: 70rpx 70rpx 10rpx 70rpx;
      justify-content: space-between;

      .t {
        width: 110rpx;
        height: 110rpx;
        background: #fff;
        border-radius: 30rpx;
        position: relative;

        text {
          position: absolute;
          bottom: -40rpx;
          font-size: 24rpx;
          line-height: 1;
          width: 110rpx;
          left: 0;
          text-align: center;
          color: #333;
        }
      }

      .iconfont {
        font-size: 46rpx;
        line-height: 110rpx;
        text-align: center;
      }
    }

    .emoji {
      height: calc(100% - 30rpx);
      overflow-y: scroll;
      padding: 15rpx;

      .emoji-img {
        width: 72rpx;
        height: 72rpx;
        margin: 15rpx;
      }
    }
  }

  .record {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    padding: 220rpx 0;
    background: linear-gradient(#3b8aff, #4cb8ff);
    z-index: 999;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: all 0.3s;

    .cancel {
      width: 70rpx;
      height: 40rpx;
      text-align: center;
      line-height: 37rpx;
      position: absolute;
      right: 30rpx;
      font-size: 25rpx;
      top: 90rpx;
      color: #fff;
      opacity: 0.8;
      border-radius: 20rpx;
      border: 1rpx solid #fff;
    }

    .time {
      font-size: 28rpx;
      text-align: center;
      margin: 0 auto;
      letter-spacing: 2rpx;
      color: #fff;
      font-size: 52rpx;
    }

    .loading {
      width: 160rpx;
      height: 40rpx;
      display: flex;
      justify-content: space-between;
      margin: 0 auto 120rpx;
      opacity: 0;

      span {
        display: inline-block;
        width: 8rpx;
        height: 100%;
        border-radius: 4rpx;
        background: lightgreen;
      }

      &.on {
        opacity: 1;

        span {
          -webkit-animation: load 0.8s ease infinite;
        }
      }

      span:nth-child(2) {
        -webkit-animation-delay: 0.13s;
      }

      span:nth-child(3) {
        -webkit-animation-delay: 0.26s;
      }

      span:nth-child(4) {
        -webkit-animation-delay: 0.39s;
      }

      span:nth-child(5) {
        -webkit-animation-delay: 0.52s;
      }
    }

    .trigger {
      width: 220rpx;
      height: 220rpx;
      margin: 0 auto;
      position: relative;

      &::after {
        content: '长按录音';
        width: 4em;
        position: absolute;
        bottom: -70rpx;
        color: #f1f1f1;
        font-size: 26rpx;
        left: 50%;
        transform: translateX(-50%);
      }

      &.reset::after {
        content: '点击可重置';
        position: absolute;
        width: 5em;
        bottom: -70rpx;
        color: #f1f1f1;
        font-size: 26rpx;
        left: 50%;
        transform: translateX(-50%);
      }

      .switch {
        width: 200rpx;
        height: 200rpx;
        border-radius: 50%;
        left: 50%;
        top: 50%;
        bottom: 200rpx;
        position: absolute;
        transform: translate(-50%, -50%);
        background-color: rgba(255, 255, 255, 0.5);
      }

      .major {
        width: 150rpx;
        height: 150rpx;
        position: absolute;
        top: 50%;
        left: 50%;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        background: #fff url(@/static/mic-blue.png) center center no-repeat;
        background-size: 40% 40%;
        opacity: 0.8;

        &.reset {
          background: #fff url(@/static/chongzhi.png) center center no-repeat;
          background-size: 40% 40%;
        }
      }

      &.on {
        .switch {
          animation: breathe 0.6s alternate infinite;
        }

        .major {
          background: rgba(59, 138, 255, 0.8) url(@/static/mic-white.png) center center no-repeat;
          background-size: 40% 40%;
        }
      }
    }

    .btns {
      height: 120rpx;
      line-height: 120rpx;
      color: #fff;

      view {
        display: flex;
        justify-content: space-between;
        padding: 0 60rpx;

        .btn {
          width: 120rpx;
          height: 120rpx;
          line-height: 120rpx;
          text-align: center;
          border-radius: 50%;
          background: #fff;
        }
      }
    }
  }
}

.content {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.face {
  // margin-top:5rpx;
}

.icon-fanhui,
.icon-gengduo {
  font-size: 42rpx !important;
}
</style>
